#include "jdv.hh"

Jdv::Jdv ()
{
  map_ = Map::instance ();
}

Jdv::Jdv (std::string in)
{
  file_ = in;
  total_cycles_ = 0;
  curr_cycle_ = 0;
  map_ = Map::instance ();
}

Jdv::Jdv (std::string in,
	  std::string nb)
{
  int pos;

  file_ = in;
  std::istringstream w (nb);
  if (w >> pos)
    total_cycles_ = pos;
  curr_cycle_ = 0;
  map_ = Map::instance ();
}

Jdv::~Jdv ()
{

}


void
Jdv::open ()
{
  if (file_ != "")
  {
    file_in_.open (file_.c_str ());
    if (file_in_ == 0)
      throw MyErrors (1);
  }
}

void
Jdv::close ()
{
  file_in_.close();
}

//
// seed nb
// map nb nb
// team [begin] --> [end]
// ressource [begin] --> [end]
// obstaccle [begin] --> [end]
//
void
Jdv::read_file ()
{
  std::string	str;
  int		posx;
  int		posy;
  int		nb_team = 1;
  std::istringstream w;

  while (file_in_ >> str)
    if (str == "seed")
    {
      file_in_ >> str;
      std::istringstream w (str);
      if (w >> posx)
	map_->set_seed (posx);
    }
    else if (str == "map")
    {
      file_in_ >> str;
      std::istringstream w (str);

      if (w >> posx)
      {
	file_in_ >> str;
	std::istringstream w (str);

	if (w >> posy)
	  map_->set_wh (posx, posy);
	else
	  throw MyErrors (1);
      }
      else
	throw MyErrors (2);
    }
    else if (str == "team" ||
	     str == "resource" ||
	     str == "obstacle")
    {
      try
      {
	parse_bloc (str, &nb_team);
      }
      catch (MyErrors& err)
      {
	err.parse_error_print ();
      }
    }
    else
      throw MyErrors (3);
}

bool
Jdv::parse_bloc_sub (int* posx, int* posy)
{
  std::string	str;

  file_in_ >> str;
  std::istringstream w (str);
  if (w >> *posx)
    {
      file_in_ >> str;
      std::istringstream w (str);
      if (w >> *posy)
	{
	  (*posy)--;
	  (*posx)--;
	  return true;
	}
    }
  throw MyErrors (1);
  return false;
}

void
Jdv::parse_bloc (std::string type, int* nb_team)
{
  std::string	str;
  std::string	name;
  int		posx;
  int		posy;
  std::istringstream w;

  try
  {
    if (type == "team")
    {
      teams_.push_back (new Team ());
      teams_.back ()->set_id ((*nb_team)++);
    }
    while (file_in_ >> str && str != "end")
    {
      name = str;
      if (type == "obstacle")
      {
	if (parse_bloc_sub (&posx, &posy))
	  map_->add_obstacle (posx, posy);
      }
      else if (type == "team")
      {
	if (parse_bloc_sub (&posx, &posy))
	{
	  map_->add_ant (posx, posy,
			teams_.back ()->add_ant (name, posx, posy));
	}
      }
      else if (type == "resource")
	if (parse_bloc_sub (&posx, &posy))
	  map_->add_ressource (name, posx, posy);
	else
	  throw MyErrors (1);
      else
	throw MyErrors (2);
    }
  }
  catch (MyErrors& err)
  {
    err.pos_not_empty_error_print ();
  }
}

// no queen in a team at most
// no teams
// no maps
void
Jdv::check ()
{
  std::vector<Team*>::iterator it;
  std::vector<Ants*>::iterator jt;
  bool is_queen = false;

  if (teams_.empty ())
    throw MyErrors (1);
  else if (map_->get_tab ().empty ())
    throw MyErrors (2);
  else
    {
      for (it = teams_.begin (); it != teams_.end (); it++)
      {
	is_queen = false;
	for (jt = (*it)->get_ant ().begin (); jt != (*it)->get_ant ().end () && is_queen == false; jt++)
	  if (dynamic_cast<Queen*>(*jt))
	    is_queen = true;
      }
      if (!is_queen)
	throw MyErrors (3);
    }
}

void
Jdv::move ()
{
  std::vector<Team*>::iterator	it;

  for (it = teams_.begin (); it != teams_.end (); it++)
    (*it)->move ();
}

int
Jdv::run ()
{
  try
  {
    open ();
  }
  catch (MyErrors& err)
  {
    err.open_error_print ();
  }

  try
  {
    read_file ();
  }
  catch (MyErrors& err)
  {
    err.read_error_print ();
  }
  close ();

  try
  {
    check ();
  }
  catch (MyErrors& err)
  {
    err.init_error_print ();
  }

  srand (map_->get_seed ());

  for (curr_cycle_ = 0; curr_cycle_ < total_cycles_; curr_cycle_++)
  {
    move ();
  }
  print ();

  return err_.get_err ();
}
